home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / amok_lha / amok24.lha / TurboFiles / TurboFiles.mod < prev    next >
Text File  |  1993-08-15  |  18KB  |  601 lines

  1. (**********************************************************************
  2.   :Program.    TurboFiles.mod
  3.   :Contents.   Replacement of the AM-FileSystem
  4.   :Author.     Stefan Salewski
  5.   :Copyright.  Public Domain
  6.   :Language.   Modula-2 with INLINE-Assembler-Code
  7.   :Imports.    Assembler2
  8.   :Translator. M2Amiga AMSoft V3.2d
  9.   :History.    V1.0 1.Jul.1989
  10.   :Address.    Stolper Weg 3, D-2160 Stade
  11. **********************************************************************)
  12.  
  13. IMPLEMENTATION MODULE TurboFiles;
  14. (* 
  15.   Created: 4/89
  16.   Changed: 12.5.89/13.5.89/20.5.89/28.5.89/31.5.89/9.6.89/13.6.89/
  17.            15.6.89/21.6.89/1.7.89 by
  18.   Stefan Salewski
  19.   Stolper Weg 3
  20.   D-2160 Stade
  21. *)
  22.   IMPORT Dos;
  23.   FROM Assembler2 IMPORT MinLongInt,MaxLongInt,MaxCard;
  24.   FROM SYSTEM IMPORT ADDRESS,ADR,BYTE,CAST,INLINE;
  25.   FROM Arts IMPORT TermProcedure,CurrentLevel,Assert;
  26.   FROM Exec IMPORT AllocMem,CopyMem,FreeMem,MemReqs,MemReqSet,UByte;
  27.   FROM RandomNumber IMPORT PutSeed,RND;
  28.   FROM Str IMPORT Length;
  29.   
  30.   VAR
  31.     fileList,dummyFile:FilePtr;
  32.     DosBase:ADDRESS;
  33.     startLevel:INTEGER; (* only for Loader/Debugger *)
  34.     
  35.   PROCEDURE Lookup(VAR f:FilePtr;VAR name:ARRAY OF CHAR;
  36.                    bufferSize:CARDINAL;mode:AccessMode):TurboResult;
  37.     VAR
  38.       buf:ADDRESS;
  39.       l:LONGINT;
  40.   BEGIN
  41.     f:=AllocMem(SIZE(File),MemReqSet{public});
  42.     IF f=NIL THEN
  43.       RETURN outOfMem
  44.     END;
  45.     bufferSize:=MaxCard(bufferSize,1);
  46.     buf:=AllocMem(bufferSize,MemReqSet{public});
  47.     IF buf=NIL THEN
  48.       FreeMem(f,SIZE(File));
  49.       RETURN outOfMem
  50.     END;
  51.     f^.fhPtr:=Dos.Open(ADR(name),mode);
  52.     IF f^.fhPtr=NIL THEN
  53.       FreeMem(f,SIZE(File));
  54.       FreeMem(buf,bufferSize);
  55.       f:=NIL;
  56.       RETURN openError;
  57.     ELSE
  58.       f^.base:=buf;
  59.       f^.dosBase:=DosBase;
  60.       (*f^.writeBase=f^.act will be initialized by the first call 
  61.                                                     of WriteBytes *)
  62.       f^.writeTop:=f^.base;
  63.       f^.filePos:=0;
  64.       f^.top:=f^.base+LONGINT(bufferSize);
  65.       f^.act:=f^.base;
  66.       f^.readTop:=f^.base;
  67.       f^.res:=done;
  68.       IF mode=NewFile THEN
  69.         f^.startLength:=0
  70.       ELSE
  71.         l:=Dos.Seek(f^.fhPtr,0,Dos.end);
  72.         f^.startLength:=Dos.Seek(f^.fhPtr,0,Dos.beginning)
  73.       END;
  74.       f^.next:=fileList;
  75.       fileList:=f;
  76.       RETURN done;
  77.     END;
  78.   END Lookup;
  79.       
  80.   PROCEDURE CloseFile(VAR f:FilePtr);
  81.     VAR
  82.       l:LONGINT;
  83.       currentFile,prevFile:FilePtr;
  84.   BEGIN
  85.     IF f^.writeTop>f^.base THEN
  86.       l:=Dos.Seek(f^.fhPtr,f^.writeBase-f^.readTop,Dos.current);
  87.       l:=Dos.Write(f^.fhPtr,f^.writeBase,f^.writeTop-f^.writeBase);
  88.     END;
  89.     Dos.Close(f^.fhPtr);
  90.     IF f=fileList THEN
  91.       fileList:=f^.next
  92.     ELSE
  93.       currentFile:=fileList;
  94.       WHILE (currentFile#f) AND (currentFile#NIL) DO
  95.         prevFile:=currentFile;
  96.         currentFile:=currentFile^.next
  97.       END;
  98.       Assert(currentFile#NIL,ADR('TurboFiles.Close: File not Found'));
  99.       prevFile^.next:=currentFile^.next
  100.     END;
  101.     FreeMem(f^.base,f^.top-f^.base);
  102.     FreeMem(f,SIZE(f));
  103.     f:=NIL;
  104.   END CloseFile;
  105.   
  106.   PROCEDURE DeleteFile(VAR fileName:ARRAY OF CHAR):BOOLEAN;
  107.   BEGIN
  108.     RETURN Dos.DeleteFile(ADR(fileName));
  109.   END DeleteFile;
  110.   
  111.   PROCEDURE ReadBytes(f:FilePtr;adr:ADDRESS;
  112.                       len:LONGINT;VAR actual:LONGINT);
  113.     VAR
  114.       toRead,l:LONGINT;
  115.   BEGIN
  116.     actual:=0;
  117.     IF (f^.res#done) OR (len<=0) THEN
  118.       RETURN
  119.     END;
  120.     LOOP
  121.       IF f^.act>=f^.readTop THEN
  122.         IF f^.writeTop>f^.base THEN
  123.           l:=Dos.Seek(f^.fhPtr,f^.writeBase-f^.readTop,Dos.current);
  124.           toRead:=f^.writeTop-f^.writeBase;
  125.           l:=Dos.Write(f^.fhPtr,f^.writeBase,toRead);
  126.           IF l<toRead THEN
  127.             f^.res:=writeError;
  128.             EXIT
  129.           END;
  130.           toRead:=f^.act-f^.writeTop;
  131.           IF toRead#0 THEN
  132.             l:=Dos.Seek(f^.fhPtr,toRead,Dos.current)
  133.           END;
  134.           f^.filePos:=f^.filePos+f^.act-f^.readTop;
  135.           f^.writeTop:=f^.base;
  136.         END;
  137.         l:=Dos.Read(f^.fhPtr,f^.base,f^.top-f^.base);
  138.         INC(f^.filePos,l);
  139.         IF l=0 THEN
  140.           f^.res:=endOfFile;
  141.           EXIT
  142.         END;
  143.         f^.act:=f^.base;
  144.         f^.readTop:=f^.base+l;
  145.       END;
  146.       toRead:=MinLongInt(f^.readTop-f^.act,len);
  147.       CopyMem(f^.act,adr,toRead);
  148.       INC(f^.act,toRead);
  149.       INC(adr,toRead);
  150.       DEC(len,toRead);
  151.       INC(actual,toRead);
  152.       IF len=0 THEN
  153.         EXIT
  154.       END
  155.     END;
  156.   END ReadBytes;
  157.  
  158.   PROCEDURE TurboRead(f{10}:FilePtr;adr{6}:ADDRESS;
  159.                       len{7}:LONGINT;VAR actual{11}:LONGINT);
  160.   (*$E-*)
  161.   BEGIN
  162.     INLINE(
  163.       04293H,00C2AH,00001H,00028H,06600H,000C8H,04A87H,06F00H,
  164.       000C2H,0282AH,00018H,0B8AAH,0001CH,06D7CH,02A2AH,00008H,
  165.       0BAAAH,00024H,0674EH,0242AH,00020H,094AAH,0001CH,07600H,
  166.       0222AH,00000H,02C6AH,00004H,04EAEH,0FFBEH,0262AH,00024H,
  167.       096AAH,00020H,0222AH,00000H,0242AH,00020H,04EAEH,0FFD0H,
  168.       0B680H,06670H,02404H,094AAH,00024H,0670AH,0222AH,00000H,
  169.       07600H,04EAEH,0FFBEH,02004H,090AAH,0001CH,0D1AAH,00010H,
  170.       02545H,00024H,0262AH,0000CH,09685H,0222AH,00000H,02405H,
  171.       02C6AH,00004H,04EAEH,0FFD6H,04A80H,06740H,0D1AAH,00010H,
  172.       02805H,0D085H,02540H,0001CH,0202AH,0001CH,09084H,0B087H,
  173.       06F02H,02007H,0D193H,09E80H,05380H,02044H,02246H,012D8H,
  174.       051C8H,0FFFCH,02808H,02C09H,04A87H,06600H,0FF5AH,02544H,
  175.       00018H,04E75H,0157CH,00005H,00028H,06006H,0157CH,00007H,
  176.       00028H,02544H,00018H,04E75H);
  177.   END TurboRead;
  178.   
  179.   PROCEDURE WriteBytes(f:FilePtr;adr:ADDRESS;len:LONGINT);
  180.     VAR
  181.       toWrite,l:LONGINT;
  182.   BEGIN
  183.     IF (f^.res#done) OR (len<=0) THEN
  184.       RETURN
  185.     END;
  186.     IF f^.writeTop=f^.base THEN
  187.       f^.writeBase:=f^.act
  188.     END;
  189.     LOOP
  190.       IF f^.act=f^.top THEN
  191.         IF f^.writeTop>f^.base THEN
  192.           l:=Dos.Seek(f^.fhPtr,f^.writeBase-f^.readTop,Dos.current);
  193.           toWrite:=f^.writeTop-f^.writeBase;
  194.           l:=Dos.Write(f^.fhPtr,f^.writeBase,toWrite);
  195.           IF l<toWrite THEN
  196.             f^.res:=writeError;
  197.             EXIT
  198.           END;
  199.           toWrite:=f^.act-f^.writeTop;
  200.           IF toWrite#0 THEN
  201.             l:=Dos.Seek(f^.fhPtr,toWrite,Dos.current)
  202.           END;
  203.           f^.filePos:=f^.filePos+f^.act-f^.readTop;
  204.           f^.writeTop:=f^.base;
  205.         END;
  206.         f^.writeBase:=f^.base;
  207.         f^.act:=f^.base;
  208.         f^.readTop:=f^.base;
  209.       END;
  210.       toWrite:=MinLongInt(f^.top-f^.act,len);
  211.       CopyMem(adr,f^.act,toWrite);
  212.       INC(adr,toWrite);
  213.       INC(f^.act,toWrite);
  214.       DEC(len,toWrite);
  215.       f^.writeTop:=f^.act;
  216.       IF len=0 THEN
  217.         EXIT
  218.       END
  219.     END;
  220.   END WriteBytes;
  221.   
  222.   PROCEDURE TurboWrite(f{10}:FilePtr;adr{11}:ADDRESS;len{7}:LONGINT);
  223.   (*$E-*)
  224.   BEGIN
  225.     INLINE(
  226.       00C2AH,00001H,00028H,06600H,000AEH,04A87H,06F00H,000A8H,
  227.       02C2AH,0000CH,02A2AH,00008H,0282AH,00018H,0BAAAH,00024H,
  228.       06604H,02544H,00020H,0BC84H,06E5EH,0BAAAH,00024H,0674EH,
  229.       0242AH,00020H,094AAH,0001CH,07600H,0222AH,00000H,02C6AH,
  230.       00004H,04EAEH,0FFBEH,0262AH,00024H,096AAH,00020H,0222AH,
  231.       00000H,0242AH,00020H,04EAEH,0FFD0H,0B680H,06652H,02404H,
  232.       094AAH,00024H,0670AH,0222AH,00000H,07600H,04EAEH,0FFBEH,
  233.       02004H,090AAH,0001CH,0D1AAH,00010H,02545H,00024H,02545H,
  234.       00020H,02805H,02545H,0001CH,02006H,09084H,0B087H,06F02H,
  235.       02007H,09E80H,05380H,02044H,010DBH,051C8H,0FFFCH,02808H,
  236.       02548H,00024H,04A87H,06600H,0FF7EH,02544H,00018H,04E75H,
  237.       0157CH,00005H,00028H,02544H,00018H,04E75H);
  238.   END TurboWrite;
  239.   
  240.   PROCEDURE ReadChar(f:FilePtr;VAR ch:CHAR);
  241.     VAR
  242.       len:LONGINT;
  243.   BEGIN
  244.     TurboRead(f,ADR(ch),1,len)
  245.   END ReadChar;
  246.   
  247.   PROCEDURE WriteChar(f:FilePtr;ch:CHAR);
  248.   BEGIN
  249.     TurboWrite(f,ADR(ch),1)
  250.   END WriteChar;
  251.   
  252.   PROCEDURE ReadByteBlock(f:FilePtr;VAR block:ARRAY OF BYTE);
  253.     VAR
  254.       len:LONGINT;
  255.   BEGIN
  256.     TurboRead(f,ADR(block),SIZE(block),len)
  257.   END ReadByteBlock;
  258.   
  259.   PROCEDURE WriteByteBlock(f:FilePtr;VAR block:ARRAY OF BYTE);
  260.   BEGIN
  261.     TurboWrite(f,ADR(block),SIZE(block))
  262.   END WriteByteBlock;
  263.  
  264.   PROCEDURE GetPos(f:FilePtr):LONGINT;
  265.   BEGIN
  266.     IF f^.res#done THEN
  267.       RETURN -1
  268.     ELSE
  269.       RETURN f^.filePos+f^.act-f^.readTop
  270.     END
  271.   END GetPos;
  272.   
  273.   (*$F-*)
  274.   PROCEDURE TurboGetPos(f{11}:FilePtr):LONGINT;
  275.   (*$E-*)
  276.   BEGIN
  277.     INLINE(
  278.       00C2BH,00001H,00028H,0660EH,0202BH,00010H,0D0ABH,00018H,
  279.       090ABH,0001CH,04E75H,070FFH,04E75H);
  280.   END TurboGetPos;(*$F=*)
  281.  
  282.   PROCEDURE SetPos(f:FilePtr;offset:LONGINT;mode:SetPosMode):BOOLEAN;
  283.     VAR
  284.       l,newPos,bufTop,getPos:ADDRESS;
  285.   BEGIN
  286.     IF f^.res#done THEN
  287.       RETURN FALSE
  288.     END;
  289.     f^.startLength:=FileLength(f);
  290.     getPos:=f^.filePos+f^.act-f^.readTop;
  291.     bufTop:=MaxLongInt(f^.readTop,f^.act);
  292.     IF mode=beginning THEN
  293.       offset:=ABS(offset)-getPos
  294.     ELSIF mode=end THEN
  295.       offset:=f^.startLength-getPos-ABS(offset)
  296.     END;
  297.     newPos:=f^.act+offset;
  298.     IF (newPos>=f^.base) AND (newPos<bufTop) THEN
  299.       f^.act:=newPos;
  300.       RETURN TRUE
  301.     ELSE
  302.       newPos:=getPos+offset;
  303.       IF (newPos<0) OR (newPos>f^.startLength) THEN
  304.         f^.res:=seekError;
  305.         RETURN FALSE
  306.       ELSE
  307.         IF f^.writeTop>f^.base THEN
  308.           l:=Dos.Seek(f^.fhPtr,f^.writeBase-f^.readTop,Dos.current);
  309.           getPos:=f^.writeTop-f^.writeBase;
  310.           l:=Dos.Write(f^.fhPtr,f^.writeBase,getPos);
  311.           IF l<getPos THEN
  312.             f^.res:=writeError;
  313.             RETURN FALSE
  314.           END;
  315.           f^.writeTop:=f^.base
  316.         END;
  317.         l:=Dos.Seek(f^.fhPtr,newPos,Dos.beginning);
  318.         f^.filePos:=newPos;
  319.         f^.act:=f^.base;
  320.         f^.readTop:=f^.base;
  321.         RETURN TRUE;
  322.       END;
  323.     END;
  324.   END SetPos;
  325.  
  326.   (*$F-*)  
  327.   PROCEDURE TurboSetPos(f{10}:FilePtr;offset{6}:LONGINT;
  328.                         mode{7}:SetPosMode):BOOLEAN;
  329.   (*$E-*)
  330.   BEGIN
  331.     INLINE(
  332.       00C2AH,00001H,00028H,06600H,000D6H,0266AH,00008H,0222AH,
  333.       00018H,0242AH,00010H,0D481H,094AAH,0001CH,02A2AH,00014H,
  334.       0BA82H,06C06H,02A02H,02545H,00014H,0262AH,0001CH,0B681H,
  335.       06C02H,02601H,00C07H,00001H,06716H,04A86H,06A02H,04486H,
  336.       00C07H,00000H,06604H,09C82H,06006H,04486H,0DC85H,09C82H,
  337.       02801H,0D886H,0B8AAH,00008H,06D0CH,0B883H,06C08H,02544H,
  338.       00018H,070FFH,04E75H,02802H,0D886H,04A84H,06B6AH,0B885H,
  339.       06E66H,0B7EAH,00024H,06732H,0222AH,00000H,0242AH,00020H,
  340.       094AAH,0001CH,07600H,02C6AH,00004H,04EAEH,0FFBEH,0222AH,
  341.       00000H,0242AH,00020H,0262AH,00024H,096AAH,00020H,04EAEH,
  342.       0FFD0H,0B680H,0662AH,0254BH,00024H,0222AH,00000H,02404H,
  343.       076FFH,02C6AH,00004H,04EAEH,0FFBEH,04A80H,06B1AH,02544H,
  344.       00010H,0254BH,00018H,0254BH,0001CH,01038H,0FFFFH,04E75H,
  345.       0157CH,00005H,00028H,06006H,0157CH,00006H,00028H,07000H,
  346.       04E75H);
  347.   END TurboSetPos;(*$F=*)
  348.   
  349.   PROCEDURE FileLength(f:FilePtr):LONGINT;
  350.   VAR
  351.     getPos:LONGINT;
  352.   BEGIN
  353.     IF f^.res#done THEN
  354.       RETURN -1
  355.     END;
  356.     getPos:=f^.filePos+f^.act-f^.readTop;
  357.     RETURN MaxLongInt(f^.startLength,getPos);
  358.   END FileLength;
  359.   
  360.   (*$F-*)
  361.   PROCEDURE TurboFileLength(f{11}:FilePtr):LONGINT;
  362.   (*$E-*)
  363.   BEGIN
  364.     INLINE(
  365.       00C2BH,00001H,00028H,06618H,0202BH,00010H,0D0ABH,00018H,
  366.       090ABH,0001CH,0222BH,00014H,0B081H,06C06H,02001H,04E75H,
  367.       070FFH,04E75H);
  368.   END TurboFileLength;(*$F=*)
  369.   
  370.   PROCEDURE Search(f:FilePtr;VAR str:ARRAY OF BYTE;len:LONGINT):LONGINT;
  371.   VAR
  372.     i,act:LONGINT;
  373.     b:CHAR;
  374.   BEGIN
  375.     IF (len>SIZE(str)) OR (len<=0) THEN
  376.       len:=SIZE(str)
  377.     END;
  378.     DEC(len);
  379.     LOOP
  380.       i:=0;
  381.       LOOP
  382.         TurboRead(f,ADR(b),1,act);
  383.         IF (b#CAST(CHAR,str[i])) OR (i=len) THEN
  384.           EXIT
  385.         END;
  386.         INC(i);
  387.       END;
  388.       IF (CAST(CHAR,str[i])=b) AND TurboSetPos(f,-i-1,current) THEN
  389.         RETURN TurboGetPos(f)
  390.       ELSIF NOT TurboSetPos(f,-i,current) THEN
  391.         RETURN -1
  392.       END;
  393.     END;
  394.   END Search;
  395.   
  396.   PROCEDURE Code(fileName,codeWord:ARRAY OF CHAR;decode:BOOLEAN):BOOLEAN;
  397.     CONST
  398.       Mult=2;
  399.       CodeStringSize=255;
  400.     TYPE
  401.       Long=[0..CodeStringSize];
  402.       CodeString=ARRAY Long OF UByte;
  403.       
  404.     PROCEDURE Permute(VAR index,code:CodeString;len:INTEGER);
  405.     VAR
  406.       qsum:LONGINT;
  407.       i,try:INTEGER;
  408.       free:ARRAY Long OF BOOLEAN;
  409.     BEGIN
  410.       (* generating a permutation of the numbers 0..(len-1).
  411.          This permutation depends on code and will be
  412.          stored in index
  413.       *)
  414.       qsum:=0;
  415.       FOR i:=0 TO len-1 DO
  416.         INC(qsum,code[i])
  417.       END;
  418.       PutSeed(qsum);
  419.       FOR i:=0 TO len-1 DO
  420.         free[i]:=TRUE;
  421.       END;
  422.       i:=0;
  423.       REPEAT
  424.         try:=RND(len);
  425.         IF free[try] THEN
  426.           index[i]:=try;
  427.           free[try]:=FALSE;
  428.           INC(i);
  429.         END;
  430.       UNTIL i=len;
  431.     END Permute;
  432.   
  433.     VAR
  434.       act,i:LONGINT;
  435.       cWLen:LONGINT;
  436.       fPtr:FilePtr;
  437.       eof:BOOLEAN;
  438.       code,readPuffer,writePuffer,index:CodeString;
  439.   BEGIN
  440.     cWLen:=MinLongInt(Length(codeWord),CodeStringSize);
  441.     CopyMem(ADR(codeWord),ADR(code),cWLen+1);
  442.     IF cWLen=0 THEN 
  443.       RETURN FALSE
  444.     END;
  445.     IF Lookup(fPtr,fileName,512,ReadWrite)=done THEN
  446.       WHILE cWLen*2<CodeStringSize DO
  447.         CopyMem(ADR(code),ADR(code)+cWLen,cWLen+1);
  448.         INC(cWLen,cWLen);
  449.       END;
  450.       Permute(index,code,cWLen);
  451.       FOR i:=0 TO cWLen-1 DO
  452.         (*$V-*)
  453.         code[i]:=code[i]*Mult;
  454.         (*$V=*)
  455.       END;
  456.       eof:=FALSE;
  457.       WHILE NOT eof DO
  458.         TurboRead(fPtr,ADR(readPuffer),cWLen,act);
  459.         IF act<cWLen THEN
  460.           eof:=TRUE;
  461.           fPtr^.res:=done; (* So I can write to the file again *)
  462.           Permute(index,code,act)
  463.         END;
  464.         IF NOT decode THEN
  465.           FOR i:=0 TO act-1 DO
  466.             (*$V-*)
  467.             INC(readPuffer[i],code[i])
  468.             (*$V=*)
  469.           END;
  470.           FOR i:=0 TO act-1 DO
  471.             writePuffer[i]:=readPuffer[index[i]]
  472.           END;
  473.         ELSE
  474.           FOR i:=0 TO act-1 DO
  475.             writePuffer[index[i]]:=readPuffer[i]
  476.           END;
  477.           FOR i:=0 TO act-1 DO
  478.             (*$V-*)
  479.             DEC(writePuffer[i],code[i])
  480.             (*$V=*)
  481.           END;
  482.         END;
  483.         IF TurboSetPos(fPtr,-act,current) THEN END;
  484.         TurboWrite(fPtr,ADR(writePuffer),act)
  485.       END;
  486.       CloseFile(fPtr);
  487.       RETURN TRUE
  488.     ELSE
  489.       RETURN FALSE
  490.     END;
  491.   END Code;
  492.   
  493.   PROCEDURE Cleanup;
  494.   BEGIN
  495.     IF CurrentLevel()<=startLevel THEN
  496.       WHILE fileList#NIL DO
  497.         dummyFile:=fileList;
  498.         CloseFile(dummyFile)
  499.       END;
  500.     END
  501.   END Cleanup;
  502.  
  503. BEGIN
  504.   fileList:=NIL;
  505.   startLevel:=CurrentLevel();
  506.   DosBase:=ADR(Dos);
  507.   TermProcedure(Cleanup);
  508. END TurboFiles.mod
  509.  
  510. (*
  511. Now a short explaination of the datastructures I use:
  512. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  513.  
  514. CONST   *** the accessmodes for the File
  515.     ReadOnly = Dos.readOnly;
  516.     ReadWrite= Dos.readWrite;
  517.     NewFile  = Dos.newFile;
  518.   TYPE
  519.     TurboResult=(notOpen,done,notdone,openError,readError,writeError,
  520.                  seekError,endOfFile,outOfMem,tooManyFiles);
  521.             
  522.     SetPosMode=(beginning,current,end);
  523.     AccessMode=[ReadWrite..NewFile];
  524.     
  525.     FilePtr=POINTER TO File;
  526.     File=RECORD
  527.            fhPtr:Dos.FileHandlePtr;
  528.            dosBase:ADDRESS;
  529.            base:ADDRESS;
  530.            top:ADDRESS;
  531.            filePos:LONGINT;
  532.            startLength:LONGINT;
  533.            act:ADDRESS;
  534.            readTop:ADDRESS;
  535.            writeBase:ADDRESS;
  536.            writeTop:ADDRESS;
  537.            res:TurboResult;
  538.            next:FilePtr;
  539.          END;
  540.     
  541.     ***
  542.        -fpPtr is the FileHandlePtr of the Dos-File.
  543.        -dosBase is the basic-address of the Dos-functions.
  544.         This dosBase I need only to call Dos-Functions from Assembler.
  545.        -base is the base of my buffer,
  546.        -top is the top of my buffer. The size of the buffer=top-base.
  547.        -filePos is the current position in the Dos-File,
  548.         (=Dos.Seek(fhPtr,Dos.current,0)).
  549.        -startLength is the Size of the Dos-file when I open it.
  550.         Notice: I change startLength, when SetPos is called.
  551.        -act is the current position in the buffer. If you call
  552.         ReadBytes, the first Byte that you get is the byte at address act.
  553.        -readTop is used by ReadBytes. If the buffer is empty, I call
  554.         l:=Dos.Read(fhPtr,base,buffersize) to fill it.
  555.         Then readTop:=base+l.
  556.         Now the part of the buffer from base to readTop contains
  557.         defined data.
  558.        -writeBase: If the content of the buffer is changed the first
  559.         time by WriteBytes at position act, I use writeBase:=act to remember
  560.         this position. Later I save not the whole buffer to disk, but
  561.         only the bytes from writeBase to writeTop.
  562.        -writeTop is the address of the upper byte in the buffer that is
  563.         changed by WriteBytes. When WriteBytes terminates, it set
  564.         writeTop:=act.
  565.        -res is the result of every operation. If any procedure set
  566.         res to a value unequal done, then all following procedure-calls
  567.         except Close will be ignored.
  568.        -next is a pointer to the next open file.
  569.         
  570.   How did it works ?
  571.   ~~~~~~~~~~~~~~~~~~
  572.         
  573.            
  574.             top  n-1---  
  575.                    .---  b
  576.       ^            .---  u
  577. read  |     act    .---  f
  578. write |            3---  f
  579.                    2---  e
  580.                    1---  r
  581.             base   0---
  582.             
  583.   The buffer contains n=top-base bytes. base is the address of the lowest
  584.   byte of the buffer, top the address of the highest byte.
  585.   act is the current position in the buffer. ReadBytes and WriteBytes
  586.   increase act until act=readTop(ReadBytes) or until act=top(WriteBytes).
  587.   WriteBytes writes to the buffer, until act=top. Then WriteBytes saved
  588.   the changed part of the buffer (the area from writeBase to writeTop)
  589.   to disk and sets act:=base.
  590.   
  591.   If act=readTop, then ReadBytes examines if the buffer is changed by
  592.   WriteBytes( writeTop>base). If the buffer is changed, then ReadBytes
  593.   saved the changed part to disk and fills the buffer again.
  594.   readTop shows which part of the buffer is filled with data.
  595.   Allways the relation holds:
  596.   base <= readTop <= top
  597.   
  598.   Stefan Salewski, 26.5.89
  599.   
  600.   *)         
  601.